/**
 * Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.common.web.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.SqlTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.swan.bean.MessageBean;

import com.koron.common.bean.StaffBean;
import com.koron.common.web.bean.DepartmentBean;
import com.koron.common.web.dto.OrgNodeDto;
import com.koron.common.web.dto.OrgStaffDto;
import com.koron.common.web.mapper.DepartmentMapper;
import com.koron.common.web.mapper.LongTreeBean;
import com.koron.common.web.mapper.StaffMapper;
import com.koron.common.web.mapper.TreeMapper;
import com.koron.util.Constant;
import com.koron.util.JsonUtils;
import com.koron.workflow.common.util.HttpUtils;

@Service
public class SynchronizationOrgService {
    
	private static final Logger LOG = LoggerFactory.getLogger(SynchronizationOrgService.class);

	@Value("${app.syn_org_url}")
	private String synOrgUrl;
	
	private static final String ROOT = "01";
	
	private static final int BATCH_COUNT = 900;
	
	public MessageBean<?> synchronization(SessionFactory factory) {
		try {
			return ADOConnection.runTask(new SqlTask() {
				@Override
				public Object run(SessionFactory factory) {
					initDepartment(factory); //初始化部门
					initTree(factory);       //初始化组织树
					initStaff(factory);      //初始化员工信息
					synDepartment(factory);  // 插入部门
					synStaff(factory);       //插入员工
					return MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "执行成功", Void.class);
				}
			}, MessageBean.class);
		}catch (Exception e) {
			e.printStackTrace();
			LOG.error("组织架构同步失败!!!!!!!" + e);
		}
		return MessageBean.create(-1, "执行失败", Void.class);
	}
	
	public MessageBean<?> synchronization() {
		try {
			return ADOConnection.runTask(new SqlTask() {
				@Override
				public Object run(SessionFactory factory) {
					initDepartment(factory); //初始化部门
					initTree(factory); //初始化组织树
					initStaff(factory); //初始化员工信息
					synDepartment(factory); // 插入部门
					synStaff(factory); //插入员工
					return MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "执行成功", Void.class);
				}
			}, MessageBean.class);
		}catch (Exception e) {
			e.printStackTrace();
			LOG.error("组织架构同步失败!!!!!!!" + e);
		}
		return MessageBean.create(-1, "执行失败", Void.class);
	}
	
	private void initDepartment(SessionFactory factory) {
		DepartmentMapper mapper = factory.getMapper(DepartmentMapper.class);
		int iCount = mapper.deleteAll();
		if(iCount > 0) {
			LOG.info("删除组织架构成功：{}", iCount);
		}
	}
	
	private void initStaff(SessionFactory factory) {
		StaffMapper mapper = factory.getMapper(StaffMapper.class);
		int iCount = mapper.deleteAll();
		if(iCount > 0) {
			LOG.info("删除员工信息成功：{}", iCount);
		}
	}
	
	private void initTree(SessionFactory factory) {
		TreeMapper mapper = factory.getMapper(TreeMapper.class);
		int iCount = mapper.deleteAll();
		if(iCount > 0) {
			LOG.info("删除组织树成功：{}", iCount);
		}
	}
	
	private void synDepartment(SessionFactory factory) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("org", ROOT);
		params.put("root", ROOT);
		params.put("secret", "workflow");
		String url = synOrgUrl + "/port/orgNode.htm";
		String data = HttpUtils.sendGetForm(url, params);
		MessageBean<?> message = JsonUtils.jsonToPojo(data, MessageBean.class);
		if(message.getCode() != Constant.MESSAGE_INT_SUCCESS) {
			LOG.error(message.getDescription());
			throw new RuntimeException("调用数据同步接口失败:" + message.getDescription());
		}
		List<OrgNodeDto> orgNodes = JsonUtils.objectToList(message.getData(), OrgNodeDto.class);
		orgNodes.remove(0);
		if(orgNodes != null && orgNodes.size() > 0) {
			batchInsertDepartment(factory, orgNodes);
			batchInsertTree(factory, orgNodes);
		}
	}

	private void synStaff(SessionFactory factory) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("org", ROOT);
		params.put("root", ROOT);
		params.put("secret", "workflow");
		String url = synOrgUrl + "/port/staff.htm";
		String data = HttpUtils.sendGetForm(url, params);
		MessageBean<?> message = JsonUtils.jsonToPojo(data, MessageBean.class);
		if(message.getCode() != Constant.MESSAGE_INT_SUCCESS) {
			LOG.error(message.getDescription());
			throw new RuntimeException("调用数据同步接口失败:" + message.getDescription());
		}
		List<OrgStaffDto> orgStaffs = JsonUtils.objectToList(message.getData(), OrgStaffDto.class);
		LOG.info("员工数量：{}", orgStaffs.size());
		if(orgStaffs != null && orgStaffs.size() > 0) {
			batchInsertStaff(factory, orgStaffs);
		}
	}
	
	private void batchInsertDepartment(SessionFactory factory, List<OrgNodeDto> orgNodes) {
		List<DepartmentBean> orgs = orgNodes.stream().map(t -> newDepartment(t)).collect(Collectors.toList());
		DepartmentMapper mapper = factory.getMapper(DepartmentMapper.class);
		int iCount = mapper.batchInsertDepartment(orgs);
		if(iCount > 0) {
			LOG.info("组织架构同步成功：{}", iCount);
		}
	}
	
	private void batchInsertTree(SessionFactory factory, List<OrgNodeDto> orgNodes) {
		List<LongTreeBean> orgs = orgNodes.stream().map(t -> newTree(t)).collect(Collectors.toList());
		LongTreeBean root = new LongTreeBean();
		root.setId(1);
		root.setForeignkey("1");
		root.setSeq(2305843009213693952L);
		root.setParentMask(0);
		root.setMask(1);
		root.setType(65536);
		root.setChildMask(4);
		orgs.add(root);
		TreeMapper mapper = factory.getMapper(TreeMapper.class);
		int iCount = mapper.batchInsertTree(orgs);
		if(iCount > 0) {
			LOG.info("组织树同步成功：{}", iCount);
		}
	}
	
	private void batchInsertStaff(SessionFactory factory, List<OrgStaffDto> orgStaffs) {
		List<StaffBean> orgs = orgStaffs.stream().map(t -> newStaff(t)).collect(Collectors.toList());
		StaffMapper mapper = factory.getMapper(StaffMapper.class);
		if(orgs.size() <= BATCH_COUNT) {
			int iCount = mapper.batchInsertStaff(orgs);
			if(iCount > 0) {
				LOG.info("员工信息同步成功：{}", iCount);
			}
		} else {
			int size = orgs.size() / BATCH_COUNT;
			int remainder = orgs.size() % BATCH_COUNT;
			for(int i = 0; i < size - 1; i++) {
				int fromIndex = i * BATCH_COUNT;
				int toIndex = (i + 1) * BATCH_COUNT;
				if((i + 2) == size && remainder > 0) {
					toIndex = toIndex + remainder;
				}
				int iCount = mapper.batchInsertStaff(orgs.subList(fromIndex, toIndex));
				if(iCount > 0) {
					LOG.info("员工信息同步成功：{}", iCount);
				}
			}
		}
	}
	
	private DepartmentBean newDepartment(OrgNodeDto org) {
		DepartmentBean department = new DepartmentBean();
		department.setId(org.getId());
		department.setName(org.getName());
		department.setDescription(org.getDescription());
		department.setFlag(org.getOrgKind());
		department.setShortname(org.getShortname());
		department.setSn(org.getWeight());
		department.setState(0);
		department.setTel(org.getPhone());
		department.setCode(org.getCode());
		if(StringUtils.isEmpty(org.getParentCode())) {
			department.setParentcode(ROOT);
		}else {
			department.setParentcode(org.getParentCode());
		}
		return department;
	}
	
	private LongTreeBean newTree(OrgNodeDto org) {
		LongTreeBean tree = new LongTreeBean();
		tree.setSeq(org.getSeq());
		tree.setParentMask(org.getParentmask());
		tree.setMask(org.getMask());
		tree.setChildMask(org.getChildmask());
		tree.setType(org.getTreeType());
		tree.setForeignkey(Integer.toString(org.getId()));
		return tree;
	}
	
	private StaffBean newStaff(OrgStaffDto org) {
		StaffBean staff = new StaffBean();
		staff.setId(org.getId());
		staff.setCode(org.getCode());
		staff.setDepartmentCode(org.getOrgNodeCode());
		staff.setDepartmentName(org.getOrgNodeName());
		staff.setEmail(org.getEmail());
		staff.setIdcard(org.getCardno());
		staff.setLoginid(org.getCode());
		staff.setLoginname(org.getName());
		staff.setMobile(org.getMobile());
		staff.setName(org.getName());
		staff.setPhone(org.getPhone());
		staff.setWeight(org.getWeight());
		staff.setStatus(0);
		staff.setPhoto(org.getLogo());
		return staff;
	}
}
